<?php

declare(strict_types=1);

namespace App\Command;

use App\Constants\Model\AdminMenu;
use App\Model\AdminRole;
use App\Model\AdminUser;
use App\Utils\Casbin;
use Hyperf\Command\Command as HyperfCommand;
use Hyperf\Command\Annotation\Command;
use Hyperf\DbConnection\Db;
use Psr\Container\ContainerInterface;

/**
 * @Command
 */
class AdminInit extends HyperfCommand
{
    /**
     * @var ContainerInterface
     */
    protected $container;

    protected $casbinInstance;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
        $this->casbinInstance = make(Casbin::class, [config('casbin.admin')]);

        parent::__construct('AdminInit');
    }

    public function configure()
    {
        parent::configure();
        $this->setDescription('导入母公司后台菜单配置');
    }

    public function handle()
    {
        $user = AdminUser::query()->first();
        $role = AdminRole::query()->first();
        $menu = \App\Model\AdminMenu::query()->first();

        if ($user || $role || $menu) {
            return;
        }
        $tree = config('menus.admin');
        $list = $this->treeToList($tree);

        $adminUser = new \App\Model\AdminUser();
        $adminUser->mobile = config('menus.default_admin_user.mobile');
        $adminUser->username = config('menus.default_admin_user.username');
        $adminUser->password = password_hash(config('menus.default_admin_user.password'), PASSWORD_BCRYPT);
        $adminUser->save();

        $adminRole = new \App\Model\AdminRole();
        $adminRole->name = config('menus.default_admin_role.name');
        $adminRole->remark = config('menus.default_admin_role.remark');
        $adminRole->save();

        $tree = config('menus.admin');
        $list = $this->treeToList($tree);
        Db::table('admin_menu')->truncate();
        Db::table('admin_menu')->insert($list);

        $adminRole->adminMenus()->sync(array_keys($list));

        $apis = Db::table('admin_menu')->where(['type' => AdminMenu::TYPE_API])->pluck('api')->toArray();

        $this->casbinInstance->setPermissionsForRole($adminRole->id, $apis);

        $this->casbinInstance->setRolesForUser($adminUser->id, [$adminRole->id]);
    }

    public function treeToList(array $tree, $pid = 0): array
    {
        $list = [];
        foreach ($tree as $node) {
            $list[$node['id']] = [
                'id' => $node['id'],
                'pid' => $pid,
                'name' => $node['name'],
                'title' => $node['title'],
                'type' => $node['type'],
                'path' => isset($node['path']) ? $node['path'] : '',
                'api' => isset($node['api']) ? $node['api'] : ''
            ];
            if (isset($node['children'])) {
                $subList = $this->treeToList($node['children'], $node['id']);
                foreach ($subList as $subNode) {
                    $list[$subNode['id']] = $subNode;
                }
            }
        }
        return $list;
    }
}
